還記得學生時期老師在教課時,一邊學習一邊抄筆記個樣子嗎?
買了一本精美的筆記,裡面寫力與美的字體,調理清晰的交代老師說了什麼,回家複習也是賞心悅目,一切就如同上了軌道般的輕鬆自在。
但老師越講越快,你就變成這個樣子
無法一個字一個字好好地寫完,
於是寫起來就變成只有自己能看懂的樣子了
至少有了草稿,而且腦中也有老師剛剛上課的內容,
下課後再把剛剛寫很亂的草稿,慢慢的把筆記做好,寫成精美的筆記
昨天介紹了如何將 records 寫入 table,使用正確的方式存進設定好的資料結構中,這種完整的寫入在 I/O 上會有時間差,完全無法應付 record 進來的速度
今天來介紹資料庫的寫入草稿 write-ahead log(WAL),好好地存入 table 我們可以比擬成寫成精美的筆記,WAL 就是我們上課所寫只有自己看得懂的鬼畫符啦~
就如同前情提要的概念一樣,先把修改的操作都先以日誌的方式存起來,等到比較不忙時,在將日誌回放(Replay),處理 index,FSM...的,正確的存到 Table 之中。
當我們在操作 SQL 指令完成後,會下 Commit,會希望資料庫能快點回應我們 Committed,因此導入了 WAL log 的機制,步驟大致如下
後續的查詢因 shared_buffers 已經修改好了,所以後續得查詢自然可以查詢的到我們已經 committed 的資料。
在 PostgreSQL 上面,WAL 以 16MB 為單位切割成 segment,WAL 也是寫到硬碟之中不是 memory 喔,,他只是非常單純的寫下 O(1)而已,所以會比存到 Table 中 O(logN)快上許多。
基本上就是 DB 的 in memory cache,當你要 CRUD 時,都會先變更 Cache 成想要的樣子。
等到 DB 有空時,在將 shared_buffers 的資料正確的落到 Disk 中,這樣就完成了一次的完整寫入,並且標註上(Checkpoint)這裡都可以在硬碟之中找到。
in memory 最怕的就是主機突然 Crash 等意外。
雖然 shared_buffers 中的所有資料都不見了,但我們還是可以透過最後一個 Checkpoint 開始還原到一個基準點,
然後在透過 WAL 回放(Redo,roll-forward recovery)一直到 shared buffers 內的資料恢復到正確的樣子,經得起查詢為止。
觸發 checkpoint 的時機點就是 DB 將 shared_buffers 的內容安全的寫入硬碟之中,這時就可以使用 checkpoint,所以我們就不需要這個 checkpoint 之前的 WAL 紀錄了。最後 checkpoint 也會建立一筆 WAL 紀錄。
前面我們使用 8 的篇幅來講解 ACID 的 I(isolation),終於要講解 A(Atomic) 了。
先來了解一下 Atomic 是什麼意思,
Atomicity 原子性:
每次的操作都是全部成功,或是全部失敗滾回,沒有其他選項。
重點在於不論 tx 中間做了哪些事情,只要需要 rollback,都可以順利的回復到原本的樣子。
那麼一個 tx 可能有許許多多的 sql command,而 db 是如何達到全部成功或失敗的呢?其實也跟 WAL 有關係
我們知道 pg 的 Write 操作都會建立一筆新的資料,在透過 clog 來判別是否需要顯示,所以
TRANSACTION_STATUS_IN_PROGRESS
改為 TRANSACTION_STATUS_COMMITTED
, 並且開始寫入 wal。TRANSACTION_STATUS_COMMITTED
,自然的我們會是他為整筆失敗。TRANSACTION_STATUS_IN_PROGRESS
改為 TRANSACTION_STATUS_ABORTED
,再來講解 ACID 的 D(durability),先來了解一下 Atomic 是什麼意思,
事務完成之後, 對系統的修改是永久性的。
重點在於 commit 時就算還沒寫完硬碟中途 crash 也救的回來。
我們知道了 WAL 寫下了在進入 table 之前的所有資料變更,並且使用了只有自己能看懂的方式交代。
資料庫剛好可以透過 預寫日誌(Write Ahead Log,WAL)的可讀複製(PITR),將 WAL 使用異步的方式,提供主從複製(Master-Slave Replication)。
透過複製 Master 的 WAL 到 Slave,讓 Slave 只需要將 WAL 的變更正確的存入 Table 內即可。
將 WAL 從 Master 傳輸到 Slave Server,然後在 Slave 上回放(Replay)出預寫日誌中記錄改動,從而實現主從複製。
PostgreSQL 使用了兩種方式傳輸預寫日誌:存檔式(archive)和流式(streaming)。
我喜歡叫他 Polling,原理大概是 Master 主動將 WAL 複製到一個安全的位置,Slave 定期去抓回來回放。
就是所謂的串流傳輸,Master 直接透過 TCP 協議來將 WAL 傳送到 Slave 中。
前面我們使用 8 的篇幅來講解 ACID 的 isolation,
這裡我們使用講解了 WAL,並且使用 wal 來完成 A(atomic)D(durability)。
當如果想要做讀寫分離,也可以使用 wal 來實作流式(streaming)與存檔式(archive)的複製。
PostgreSQL 基於預寫日誌的複製
Postgres 筆記 – Write Ahead Log (WAL)
PostgreSQL 特性介紹- WAL & checkpoint